package com.demo.db;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.his.emr.print.utils.My;

public class TemplatesDB {

	/**
	 * 这个static的列表保存用户的模板名
	 * 在启动(或第一次访问)时,读取模板文件的存放目录,同时创建`tplNameList`
	 * 在保存模板时,向`tplNameList`增加记录.
	 * tomcat停止,数据消亡
	 * 
	 * 静态(static)容器,使用不当会导致内存泄露,
	 * 这不禁让我想到数据库的一个好处: 数据库会处理内存与磁盘文件间的交换！
	 */
	private static List<String> tplNameList = null;
	
	/**
	 * 发现使用`Map`更合适
	 * `File`对象不需要直接和外部程序打交道, 提供给外部的是`String`类型的文件名称, 
	 * 外部程序通过文件名称查找File对象, 这样的话, 提供`Map`更合适!
	 */
	private static Map<String,File> tplStore = null;
	
	private static String dirForTpls;
	private static String sp = File.separator;
	
	private static String SUFFIX = ".xml";

	/**
	 * 在static域中初始化`tplNameList`,或者在构造方法中初始化,效果都是一样的！
	 * static域是只执行一次,能够确保"一次",不重复
	 * 构造方法中,就需要判断一下`tplNameList`是否为null
	 * 综上,在static域中初始化时最合适的
	 * 
	 * 但是, 获取目录需要`HttpServletRequest`, 所以还是在构造方法中初始化比较好！
	 */
	static {}
	public TemplatesDB(){
		// this.req = req;
		if(null == tplNameList){
			tplNameList = new ArrayList<String>();
			tplStore = new HashMap<String,File>();
			initTplNameList();
		}
	}
	
	public List<String> getAllTplNames(){
		return tplNameList;
	}
	
	public File getTplByName(String tplName){
		return tplStore.get(tplName);
	}
	
	public String getContentsByName(String tplName){
		File file = tplStore.get(tplName);
		StringBuffer sbb = new StringBuffer();
		BufferedReader br = null;
		try {
			br = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF8"));
			String line = null;
			while( (line=br.readLine()) != null ){
				sbb.append(line);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(null != br){
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return sbb.toString();
	}
	
	/**
	 * true : 没有重名,可以添加
	 * false : 有重名,不能添加
	 * @param tplName
	 * @return
	 */
	public boolean validate(String tplName){
		for(String item : tplNameList){
			if(tplName.equals(item)){
				return false;
			}
		}
		return true;
	}
	
	/**
	 * 保存模板,并把名称和file对象缓存起来
	 * 
	 * @param tplName
	 * @param tplContents
	 * @return
	 */
	public boolean saveTpl(String tplName, String tplContents){
		if(null == tplName || null == tplContents){
			return false;
		}
		tplName = tplName.trim();
		if(validate(tplName)){
			if(saveFile(tplName, tplContents)){
				return true;
			}else{
				return false;
			}
		}else{
			return false;
		}
	}
	
	/**
	 * 在构造方法中被执行
	 */
	private void initTplNameList(){
		// String dirForTpls = ""; // 这个变量应该提升为static成员变量,因为存储时也会使用到！
		// HttpServletRequest cannot be resolved to a type: 需要引入servlet-api-2.5.jar
		// String webpath = req.getSession().getServletContext().getRealPath("");
		
		/**
		 * 不应该保存在web目录下的, 应该通过配置文件设置目录
		 * 如果放在web目录下,重新部署时,之前的文件还得备份,否则就会丢失！
		 * //dirForTpls = webpath + sp + "store" + sp + "uetpls";
		 * 
		 * //dirForTpls = PropKit.get("tplStoreDir") + sp + "store" + sp + "uetpls";
		 * java.io.FileNotFoundException: D:\wxg\UeTplStroe\store\\uetpls\aaa.xml (系统找不到指定的路径。)
		 * 在注释里还不能出现 "\\u" (必须双斜线,单斜线就报错！~)
		 * 现在改为从配置文件读取目录, `sp + "store" + sp + "uetpls"`要去掉!!
		 * 
		 */
		// dirForTpls = PropKit.get("tplStoreDir");
		/**
		 * update 2018年2月9日: 将模板文件放到jar包内部
		 */
		dirForTpls = My.rootpath("com/his/emr/print/html/xmltpl");
		
		try {
			File uetplsDir = new File(dirForTpls);
			File[] tplfiles = uetplsDir.listFiles();
			if(null != tplfiles){
				String tplName = null;
				for(File file : tplfiles){
					/**
					 * http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/regex/Pattern.html
					 * 随着代码的演进, 我突然意识到这里应该将扩展名去掉
					 */
					tplName = file.getName().replaceAll(SUFFIX+"$", "");
					tplNameList.add(tplName);
					tplStore.put(tplName, file);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 
	 * @see wxg.test.exception.a01.ClazzA
	 * 
	 * @param tplName
	 * @param tplContents
	 * @return
	 */
	private boolean saveFile(String tplName, String tplContents){
		boolean flag = true;
		// String suffix = ".xml"; // 随着代码的演进,这里的`suffix`应该提升为成员常量!
		String filename = tplName + SUFFIX;
		String filepath = dirForTpls + sp + filename;
		
		File file = null;
		BufferedWriter bw = null;
		try {
			file = new File(filepath);
			bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream( file )));
			bw.write(tplContents);
		} catch (Exception e) {
			flag = false;
			e.printStackTrace();
		} finally {
			if(null != bw){
				try {
					bw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		// 根据 wxg.test.exception.a01.ClazzA.java的测试结果, (1) 以下代码应该放在`if(flag){...}`语句中
		if(flag){
			// (2) 或者在方法外编写这段代码
			// 这里选择(1)
			tplNameList.add(tplName);
			tplStore.put(tplName, file);
		}
		return flag;
	}
}
